package com.maxlen.camunda.listener;

import com.maxlen.camunda.constant.CamundaConstant;
import org.camunda.bpm.engine.delegate.DelegateExecution;
import org.camunda.bpm.engine.delegate.ExecutionListener;
import org.camunda.bpm.engine.impl.persistence.entity.ExecutionEntity;
import org.camunda.bpm.model.bpmn.instance.UserTask;
import org.camunda.bpm.model.bpmn.instance.camunda.CamundaProperties;
import org.camunda.bpm.model.bpmn.instance.camunda.CamundaProperty;
import org.camunda.bpm.model.xml.instance.ModelElementInstance;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Map;

/**
 * 流程箭头监听类
 * 当流程运行到箭头时被监听，此次监听查找箭头的流向是否为用户任务
 * 当为用户任务时，判断用户任务是否是并行或串行
 * 只有串行或并行时，程序获取用户任务中的外部属性 assignee ，判断是否有值
 * 如果有值，将得到的值放入流程的变量中
 * 如果没有值，判断流程变量中 assigneeList 是否有值
 * 流程变量中 assigneeList 没有值，则报异常
 */
@Component
public class FlowListener implements ExecutionListener {
    @Override
    public void notify(DelegateExecution execution) throws Exception {
        String id = ((ExecutionEntity) execution).getActivity().getOutgoingTransitions().get(0).getDestination().getId();
        if(!StringUtils.hasText(id)){
            return;
        }
        if(id.contains(CamundaConstant.ACTIVITY_SPLIT)){
            Map<String, Object> variables = execution.getProcessEngine().getRuntimeService().getVariables(execution.getId());

            String nodeId = id.split(CamundaConstant.ACTIVITY_SPLIT)[0];
            ModelElementInstance modelElementById = execution.getProcessEngine().getRepositoryService()
                    .getBpmnModelInstance(execution.getProcessDefinitionId())
                    .getModelElementById(nodeId);
            Collection<CamundaProperty> camundaPropertyCollection = ((UserTask) modelElementById)
                    .getExtensionElements()
                    .getElementsQuery()
                    .filterByType(CamundaProperties.class)
                    .singleResult()
                    .getCamundaProperties();


            Collection<String> assigneeList = new ArrayList<>();

            for (CamundaProperty camundaProperty : camundaPropertyCollection) {
                if(CamundaConstant.ASSIGNEE.equals(camundaProperty.getCamundaName())){
                    String camundaValue = camundaProperty.getCamundaValue();
                    if(camundaValue == null){
                        return;
                    }
                    String[] split = camundaValue.split(CamundaConstant.ASSIGNEE_SPLIT);
                    if(!(split.length > 0)){
                        return;
                    }
                    for (String assignee : split) {
                        if(StringUtils.hasText(assignee)){
                            assigneeList.add(assignee);
                        }
                    }
                }
            }

            if(assigneeList.isEmpty()){
                Object object = variables.get(CamundaConstant.ASSIGNEE_LIST);
                if(object instanceof ArrayList<?>){
                    for (Object o : (List<?>) object) {
                        assigneeList.add(o.toString());
                    }
                }
            }
            execution.setVariableLocal(CamundaConstant.ASSIGNEE_LIST, assigneeList);
        }
    }
}
